home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / New System Software Extensions / Thread Manager Extension 2.0.1 / Sample Applications / Power Examples / SortPicts / Source / QuickSort.cp < prev    next >
Encoding:
Text File  |  1994-06-03  |  4.3 KB  |  192 lines  |  [TEXT/MPS ]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     QuickSort.cp
  4.  
  5.     fastQSort() is a replacement for qsort().  Compared with the Think C library
  6.     version of qsort, fastQSort is about 3 times faster (it takes 1/3 the time), 
  7.     and its speed isn't dependent on the data being sorted.
  8.     
  9.     One problem with qsort is that when the data is not in random order -- for
  10.     example when it's already ordered, in reverse order, or almost sorted -- then 
  11.     qsort exhibits worst case behavior of N*N/2 operations.  For N=1024 this can 
  12.     take about 30 seconds, instead of the usual 0.8 seconds.  The fastQSort 
  13.     algorithm doesn't have this problem, because it randomly selects the pivot
  14.     element, and so for N=1024 it requires about 0.26 secs +/- 0.02 secs.
  15.     
  16.     Also, because fastQSort doesn't exhibit worst case behavior, it doesn't 
  17.     require as much stack space, even though it has 12 bytes more of local
  18.     variables.
  19.     
  20.     The things that make fastQSort so much faster than qsort are:
  21.     
  22.     1)    fastQSort picks the pivot element randomly, so it doesn't display worst
  23.         case behavior.
  24.         
  25.     2)    fastQSort uses pointers and pointer arithmetic, avoiding multiplication
  26.         whenever possible.
  27.     
  28.     3)    qsort uses std_swap() to swap the data between two locations, and 
  29.         std_swap loops through the data 3 times to perform the exchange!  In
  30.         comparison, swapMem() loops through the data just once.
  31.         
  32.     4)    fastQSort uses register variables whenever it makes good sense to do so.
  33.     
  34.     
  35.     Researched and written by:
  36.     
  37.         Haydn Huntley
  38.         Haydn's Consulting
  39.         203 West Stone
  40.         Fairfield, Iowa  52556
  41.         (515) 472-7025
  42.         
  43.     During the school year, I may be reached at the following address:
  44.     
  45.         Haydn Huntley
  46.         Eigenmann Hall #289
  47.         Indiana University
  48.         Bloomington, IN  47406
  49.         (812) 857-8620
  50.         
  51.     E-mail:  huntley@copper.ucs.indiana.edu
  52.  
  53.     This version was modified by Randy Thelen of Apple Computer, Inc.
  54.     This version works within the shell of SortPicts.
  55.     
  56.     Hopefully, we'll see faster Sorts with QuickSort than with Heap sorts and the like
  57. ----------------------------------------------------------------------------*/
  58.  
  59. #include "GWorldObj.h"
  60. #include "QuickSort.h"
  61.  
  62. #define    Data    sortListPtr
  63.  
  64. void    GWorldObj::QuickSort( void)
  65. {
  66.     long            *tickPtr = (long *)0x16A;
  67.     char            mmuMode = true32b;
  68.     
  69.     SetTitle( (const unsigned char*)"\pQuick Sorting");
  70.  
  71.     SwapMMUMode( &mmuMode);
  72.     UseGWorld();
  73. #ifdef DEMO
  74.     //    This offsets for drawing directly to the screen
  75.     offscreenPtr -= (long) ((**(((CWindowPtr)me)->portPixMap)).bounds.top * pictRowBytes) +
  76.                     (**(((CWindowPtr)me)->portPixMap)).bounds.left;
  77. #endif
  78.     
  79.     HLock( (Handle)sortList);
  80.     sortListPtr = *sortList;
  81.     if( !sortListPtr)
  82.         return;
  83.  
  84.     yieldTime = *tickPtr + gYieldDelay;
  85.  
  86.     QuickSortEngine( 0, N, &mmuMode);
  87.     
  88.     UnuseGWorld();
  89.     SwapMMUMode( &mmuMode);
  90.  
  91.     HUnlock( (Handle)sortList);
  92.     SetTitle( (const unsigned char*)"\pDone");
  93.     
  94.     doneSorting = true;
  95.     finishedTime = TickCount();
  96.     DrawObj();
  97. }
  98.  
  99.  
  100. void    GWorldObj::ChooseMedian( long a, long b, long c)
  101. {
  102.     long        m;        //    median
  103.  
  104.     if( Data[a] > Data[b])
  105.         if( Data[a] > Data[c])
  106.             if( Data[b] > Data[c])
  107.                 m = b;
  108.             else
  109.                 m = c;
  110.         else
  111.             m = a;
  112.     else
  113.         if( Data[a] > Data[c])
  114.             m = a;
  115.         else
  116.             if( Data[b] > Data[c])
  117.                 m = c;
  118.             else
  119.                 m = b;
  120.     
  121.     if( a != m)
  122.         ExchangeSortItem( a, m);
  123. }
  124.  
  125.  
  126. void    GWorldObj::QuickSortEngine( long left, long right, char *mmuMode)
  127. {
  128.     long            n;
  129.     long            i, j;
  130.     
  131.     if( doneSorting)
  132.         return;
  133.     
  134.     while( (n = right - left) > 1)
  135.     {
  136.         if( n < kPivotCutoff)        //    Use a random pivot
  137.             ExchangeSortItem( left + RandomPixel( n), left);
  138.         else
  139.             ChooseMedian( left, left + (n >> 1), 
  140.                           left + RandomPixel( n));
  141.         
  142.         i = left;
  143.         j = right;
  144.         
  145.         while( 1)
  146.         {
  147.             i++;
  148.             while( (i < right) && (Data[i] < Data[left]))
  149.                 i++;
  150.             
  151.             j--;
  152.             while( (j > left) && (Data[j] > Data[left]))
  153.                 j--;
  154.             
  155.             if( i >= j)
  156.                 break;
  157.             
  158.             ExchangeSortItem( i, j);
  159.         }
  160.         
  161.         if( j == left)
  162.         {
  163.             left++;
  164.             continue;
  165.         }
  166.         
  167.         ExchangeSortItem( left, j);
  168.         if( (j - left) < (right - (j + 1)))
  169.         {
  170.             /* equivalent to doFastQSort (j + qSize, last);        */
  171.             /* to save stack space                                */
  172.             QuickSortEngine( left, j, mmuMode);
  173.             left = j + 1;
  174.         }
  175.         else
  176.         {
  177.             /* equivalent to doFastQSort (first, j);            */
  178.             /* to save stack space                                */
  179.             QuickSortEngine( j+1, right, mmuMode);
  180.             right = j;
  181.         }
  182.  
  183.         if( YieldIfTime( mmuMode))
  184.         {
  185.             doneSorting = true;
  186.             return;
  187.         }
  188.     }
  189.  
  190. }
  191.  
  192.